package common

import (
	controllerCommon "douhu_backend/internal/controller/common"
	"douhu_backend/internal/log"
	"douhu_backend/internal/model/auth"
	"douhu_backend/internal/util"
	"fmt"
	"io"
	"mime/multipart"
	"os"
	"path/filepath"

	"github.com/kataras/iris/v12"
)

// UploadService 文件上传服务
type UploadService struct {
	uploadDir string // 上传根目录
	avatarDir string // 头像目录
	maxSize   int64  // 最大文件大小（字节）
}

// NewUploadService 创建文件上传服务
func NewUploadService() *UploadService {
	uploadDir := "./uploads"
	avatarDir := filepath.Join(uploadDir, "avatars")

	// 确保上传目录存在
	os.MkdirAll(uploadDir, 0755)
	os.MkdirAll(avatarDir, 0755)

	return &UploadService{
		uploadDir: uploadDir,
		avatarDir: avatarDir,
		maxSize:   5 * 1024 * 1024, // 默认 5MB
	}
}

// UploadFile 上传文件到指定子目录
func (s *UploadService) UploadFile(file *multipart.FileHeader, subDir string) (string, error) {
	// 检查文件大小
	if file.Size > s.maxSize {
		return "", fmt.Errorf("file size exceeds maximum limit of %d bytes", s.maxSize)
	}

	// 生成唯一文件名
	filename, err := util.GenerateUniqueFilename(file.Filename)
	if err != nil {
		return "", fmt.Errorf("failed to generate unique filename: %w", err)
	}

	// 构建完整路径
	targetDir := filepath.Join(s.uploadDir, subDir)
	if err := os.MkdirAll(targetDir, 0755); err != nil {
		return "", fmt.Errorf("failed to create upload directory: %w", err)
	}

	targetPath := filepath.Join(targetDir, filename)

	// 保存文件
	src, err := file.Open()
	if err != nil {
		return "", fmt.Errorf("failed to open uploaded file: %w", err)
	}
	defer src.Close()

	if err := s.saveFile(src, targetPath); err != nil {
		return "", fmt.Errorf("failed to save file: %w", err)
	}

	log.Infof("File uploaded successfully: %s", targetPath)

	// 返回相对路径
	return filepath.Join(subDir, filename), nil
}

// UploadAvatar 上传用户头像（中间件方法）
func (s *UploadService) UploadAvatar(ctx iris.Context) {
	// 从上下文中获取用户信息
	userInterface := ctx.Values().Get("user")
	if userInterface == nil {
		ctx.JSON(controllerCommon.RspProto{
			Code:    401,
			Message: "用户未登录",
			Data:    nil,
			Error:   "Unauthorized",
		})
		return
	}

	user, ok := userInterface.(*auth.User)
	if !ok {
		ctx.JSON(controllerCommon.RspProto{
			Code:    500,
			Message: "用户信息格式错误",
			Data:    nil,
			Error:   "Invalid user format",
		})
		return
	}

	// 解析表单数据
	file, header, err := ctx.FormFile("avatar")
	if err != nil {
		log.Errorf("get form file failed: %v", err)
		ctx.JSON(controllerCommon.RspProto{
			Code:    400,
			Message: "文件获取失败",
			Data:    nil,
			Error:   err.Error(),
		})
		return
	}
	defer file.Close()

	// 验证文件大小
	if header.Size > s.maxSize {
		ctx.JSON(controllerCommon.RspProto{
			Code:    400,
			Message: fmt.Sprintf("文件大小超过限制，最大允许%dMB", s.maxSize/(1024*1024)),
			Data:    nil,
			Error:   "File size exceeded",
		})
		return
	}

	// 验证文件类型
	if !util.IsValidImageType(header.Header.Get("Content-Type")) {
		ctx.JSON(controllerCommon.RspProto{
			Code:    400,
			Message: "不支持的文件类型，请上传JPG、PNG、GIF格式的图片",
			Data:    nil,
			Error:   "Invalid file type",
		})
		return
	}

	// 生成唯一文件名
	filename, err := util.GenerateUniqueFilename(header.Filename)
	if err != nil {
		log.Errorf("generate filename failed: %v", err)
		ctx.JSON(controllerCommon.RspProto{
			Code:    500,
			Message: "文件名生成失败",
			Data:    nil,
			Error:   err.Error(),
		})
		return
	}

	// 保存文件
	filePath := filepath.Join(s.avatarDir, filename)
	if err := s.saveFile(file, filePath); err != nil {
		log.Errorf("save file failed: %v", err)
		ctx.JSON(controllerCommon.RspProto{
			Code:    500,
			Message: "文件保存失败",
			Data:    nil,
			Error:   err.Error(),
		})
		return
	}

	// 生成文件URL
	fileURL := fmt.Sprintf("/uploads/avatars/%s", filename)

	log.Infof("avatar uploaded successfully, user_id: %d, file: %s", user.ID, filename)

	// 返回成功响应
	ctx.JSON(controllerCommon.RspProto{
		Code:    200,
		Message: "头像上传成功",
		Data: map[string]interface{}{
			"url":      fileURL,
			"filename": filename,
		},
	})
}

// DeleteFile 删除文件
func (s *UploadService) DeleteFile(relativePath string) error {
	fullPath := filepath.Join(s.uploadDir, relativePath)
	if err := os.Remove(fullPath); err != nil {
		return fmt.Errorf("failed to delete file: %w", err)
	}
	log.Infof("File deleted successfully: %s", fullPath)
	return nil
}

// ValidateFileType 验证文件类型
func (s *UploadService) ValidateFileType(filename string, allowedTypes []string) bool {
	ext := filepath.Ext(filename)
	for _, allowedType := range allowedTypes {
		if ext == allowedType {
			return true
		}
	}
	return false
}

// SetMaxSize 设置最大文件大小
func (s *UploadService) SetMaxSize(size int64) {
	s.maxSize = size
}

// SetUploadDir 设置上传根目录
func (s *UploadService) SetUploadDir(dir string) {
	s.uploadDir = dir
	s.avatarDir = filepath.Join(dir, "avatars")

	// 确保目录存在
	os.MkdirAll(s.uploadDir, 0755)
	os.MkdirAll(s.avatarDir, 0755)
}

// saveFile 保存上传的文件（私有方法）
func (s *UploadService) saveFile(src io.Reader, destPath string) error {
	// 创建目标文件
	dst, err := os.Create(destPath)
	if err != nil {
		return err
	}
	defer dst.Close()

	// 复制文件内容
	_, err = io.Copy(dst, src)
	return err
}
